package net.guerlab.smart.wx.api.autoconfig;

import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import net.guerlab.commons.exception.ApplicationException;
import net.guerlab.smart.wx.api.WxCpApi;
import net.guerlab.smart.wx.core.domain.WxCpOauth2UserInfoDTO;
import net.guerlab.smart.wx.service.service.WxCpManagerService;
import net.guerlab.smart.wx.service.service.WxMaLoginService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.lang.NonNull;

/**
 * @author guer
 */
@Configuration
@Conditional(WxCpApiLocalServiceAutoConfigure.WrapperCondition.class)
public class WxCpApiLocalServiceAutoConfigure {

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Bean
    @ConditionalOnBean(WxMaLoginService.class)
    public WxCpApi wxCpApiLocalServiceWrapper(WxCpManagerService managerService) {
        return new WxCpApiLocalServiceWrapper(managerService);
    }

    @SuppressWarnings("WeakerAccess")
    static class WrapperCondition implements Condition {

        @Override
        public boolean matches(@NonNull ConditionContext context, @NonNull AnnotatedTypeMetadata metadata) {
            try {
                ClassLoader classLoader = WxMpApiLocalServiceAutoConfigure.WrapperCondition.class.getClassLoader();
                return classLoader.loadClass("net.guerlab.smart.wx.service.service.WxCpManagerService") != null;
            } catch (Exception e) {
                return false;
            }
        }
    }

    @AllArgsConstructor
    private static class WxCpApiLocalServiceWrapper implements WxCpApi {

        private final WxCpManagerService managerService;

        @Override
        public String getAccessToken(String appId) {
            try {
                return managerService.getService(appId).getAccessToken();
            } catch (WxErrorException e) {
                throw new ApplicationException(e.getError().getErrorMsg(), e.getError().getErrorCode());
            }
        }

        @Override
        public WxCpOauth2UserInfoDTO getCodeInfo(String appId, String code) {
            try {
                WxCpOauth2UserInfo userInfo = managerService.getService(appId).getOauth2Service().getUserInfo(code);

                WxCpOauth2UserInfoDTO dto = new WxCpOauth2UserInfoDTO();
                dto.setOpenId(userInfo.getOpenId());
                dto.setDeviceId(userInfo.getDeviceId());
                dto.setUserId(userInfo.getUserId());
                dto.setUserTicket(userInfo.getUserTicket());
                dto.setExpiresIn(userInfo.getExpiresIn());

                return dto;
            } catch (WxErrorException e) {
                throw new ApplicationException(e.getError().getErrorMsg(), e.getError().getErrorCode());
            }
        }
    }

}
